package Program;

import Func.Goble;
import Func.GobleKit;
import Func.GobleTool;
import Kit.FileIO;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        Scanner scanner = new Scanner(System.in);
        String comment;
        while(true)
        {
            GobleTool.cleanner();
            GobleTool.printHelp();
            comment = scanner.next();
            if (comment.equals("exit"))
                break;
            else if(comment.equals("0"))
            {
                com0();
            }
            else if(comment.equals("1"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun1();fun2(false);fun3(false);
                //释放临时内容，降低内存使用，加速计算
                Goble.ratingList = null;
                Goble.ratingsFile = null;
                Goble.moviesFile = null;
                //释放结束
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000 + "秒");
            }
            else if(comment.equals("1.1"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun1();fun2(true);fun3(true);
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000 + "秒");
            }
            else if(comment.equals("2"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun1();fun2(false);
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000 + "秒");
            }
            else if(comment.equals("2.1"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun1();fun2(true);
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000 + "秒");
            }
            else if(comment.equals("3"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun3(false);
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000.0 + "秒");
            }
            else if(comment.equals("3.1"))
            {
                long startTime1 =  System.currentTimeMillis();
                fun3(true);
                long endTime1 =  System.currentTimeMillis();
                System.out.println((endTime1-startTime1)/1000.0 + "秒");
            }
            else if(comment.equals("4"))
            {
                fun4();
            }
            else if(comment.equals("5"))
            {
                fun5();
            }
            else if(comment.equals("5.1"))
            {
                long startTime =  System.currentTimeMillis();
                FileIO.readMovieList("d:/teamdata/cache/system/movieList.dat");
                String path="d:/teamdata/cache/endingResult.dat";
                FileIO fileIO = new FileIO();
                fileIO.readEndingResult(path);
                long endTime =  System.currentTimeMillis();
                double usedTime = (endTime-startTime)/1000.0;
                GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");
            }
            else if(comment.equals("5.2"))
            {
                List<Map.Entry<Integer,Double>> resultList;
                System.out.print("请输入视频ID:");
                Integer moviesId = scanner.nextInt();
                GobleTool.printInfo("正在进行推送计算,请稍后...");
                long startTime =  System.currentTimeMillis();
                resultList = Goble.endingResult.get(moviesId);
                for (int i=0;i<resultList.size();i++)
                {
                    Map.Entry<Integer,Double> temp = resultList.get(i);
                    System.out.println(temp.getKey()+":"+Goble.movieList.get(temp.getKey())+":"+temp.getValue());
                }
                long endTime =  System.currentTimeMillis();
                double usedTime = (endTime-startTime)/1000.0;
                GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");

            }
            else if(comment.equals("6"))
                fun6();
            else if(comment.equals("7"))
                fun7();
            else if(comment.equals("8"))
                for (Integer movieId:Goble.movieList.keySet())
                    GobleKit.readSimilarityCache(movieId);
            else if(comment.equals("9"))
            {
                for (Integer movieId:Goble.movieList.keySet())
                    GobleKit.similarity(movieId);
            }
        }
    }

    public static void com0() throws IOException
    {
        long startTime1 =  System.currentTimeMillis();
        int user_to_itemCount = 14;
        int item_to_userCount = 11;
        final CountDownLatch countDownLatch = new CountDownLatch(1+user_to_itemCount+item_to_userCount) ;
        new Thread(() -> {
            try {
                FileIO.readMovieList("d:/teamdata/cache/system/movieList.dat");
            } catch (IOException e) { e.printStackTrace(); }
            countDownLatch.countDown();
        }).start();

        for (int i=0;i<user_to_itemCount;i++)
        {
            int finalI = i;
            new Thread(() -> {
                try {
                    FileIO.readMappingItem("d:/teamdata/cache/system/user_to_item"+ finalI +".dat",0);
                } catch (IOException e) { e.printStackTrace(); }
                countDownLatch.countDown();
            }).start();
        }

        for (int i=0;i<item_to_userCount;i++)
        {
            int finalI = i;
            new Thread(() -> {
                try {
                    FileIO.readMappingItem("d:/teamdata/cache/system/item_to_user"+ finalI +".dat",1);
                } catch (IOException e) { e.printStackTrace(); }
                countDownLatch.countDown();
            }).start();
        }
        try
        {
            countDownLatch.await();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        long endTime1 =  System.currentTimeMillis();
        GobleTool.printWaitInfo((endTime1-startTime1)/1000.0 + "秒");
    }

    public static void fun1() throws IOException
    {
        FileIO io = new FileIO();
        Goble.moviesFile = io.readFile("d:/teamdata/movies.dat");
        Goble.ratingsFile = io.readFile("d:/teamdata/ratings_train.dat");
    }

    public static void fun2(boolean createCache) throws IOException
    {
        GobleKit.initMovies(Goble.moviesFile,createCache);
        GobleKit.initRatings(Goble.ratingsFile);
    }

    public static void fun3(boolean createCache) throws IOException
    {
        GobleKit.initMapping(createCache);
    }

    public static void fun4() throws IOException
    {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入视频ID:");
        Integer moviesId = scanner.nextInt();
        GobleTool.printInfo("正在进行推送计算,请稍后...");
        long startTime =  System.currentTimeMillis();
        //关键方法调用
        ArrayList<String> result = GobleKit.similarity(moviesId);
        if (result != null)
        {
            for (int i=0;i<result.size();i++)
            {
                System.out.println(result.get(i));
            }
            long endTime =  System.currentTimeMillis();
            double usedTime = (endTime-startTime)/1000.0;
            GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");
        }
    }

    public static void fun5() throws IOException
    {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入视频ID:");
        Integer moviesId = scanner.nextInt();
        long startTime =  System.currentTimeMillis();
        //关键方法调用
        ArrayList<String> result = GobleKit.readSimilarityCache(moviesId);

        for (int i=0;i<result.size();i++)
        {
            System.out.println(result.get(i));
        }
        long endTime =  System.currentTimeMillis();
        double usedTime = (endTime-startTime)/1000.0;
        GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");
    }

    public static void fun6() throws IOException
    {
        Goble.isDebug=true;
    }

    public static void fun7() throws IOException
    {
        Goble.isDebug=false;
    }
}
